<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    *{
        margin: 0;
        padding: 0;
    }

    .main{
        width: 260px;
        margin: 0 auto;
        margin-top: 50px;
    }
    .main ul{
        list-style: none;
    }
    .main ul li {
        position: relative;
        border: 1px black solid;
        line-height: 40px;
        text-indent: 2em;
        font-size: 16px;
    }
    .main ul>li:first-child {
        border-top-right-radius: 10px;
        border-top-left-radius: 10px;
    }
    .main ul>li:last-child{
        border-bottom-left-radius: 10px;
        border-bottom-right-radius: 10px;

    }
    .main ul li span {
        display: block;
        position: absolute;
        right: 10px;
        top: 5px;
        height: 30px;
        width: 30px;
        background: url(./imgs/箭头.png) no-repeat center center;
        background-size: contain;
    }
    .sub {
        display: none;
        background-color: #333;
        overflow: hidden;
    }
    .main ul li .sub li {
        box-sizing: border-box;
        color: blanchedalmond;
        border: 0px black solid;
        border-bottom: 1px black solid;
        border-bottom-left-radius: 0px;
        border-bottom-right-radius: 0px;

    }
    .sub li:hover {
        background-color: black;
    }
    .current {
        transform: rotate(90deg);
    }
</style>
<body>
    <script src='./jquery.min.js'></script>
    <script>
        $(document).ready(()=>{
            //如果鼠标滑动次数过于频繁会多次触发hover事件 此时需要函数节流来防止事件的非必要多次触发
            let toggle = function(){
                // 1.显示
                $(this).children('span').addClass('current');
                $(this).siblings().children('span').removeClass('current');
                $sub = $(this).children('.sub');
                $sub.slideDown(500);
                $(this).siblings().children('.sub').slideUp(500);
            }
            //节流函数
            /*
                函数节流是通过对定时器的操作保证一段时间内只执行一次事件触发的函数的技术，
                思路：第一次触发函数时设置一个定时器，如果再次触发该事件时定时器的回调函数还未执行，
                就不作任何回应，而当定时器执行完回调函数时将定时器清除，以保证下一次事件的正常触发。
            */
            let close = function(){
                //对事件的触发元素进行判断分别处理。
                if($(this).hasClass('sub') ){
                    console.log("触发sub")
                    $(this).slideUp(500);
                    $(this).parent().children('span').removeClass('current');
                }
                if($(this).hasClass('first')){
                    console.log("触发first")
                    $(this).children('.sub').slideUp(500);
                    $(this).children('span').removeClass('current');
                }
                console.log(this)
            }
            var throttle = function(func, delay) {            
                var timer = null;  
                return function() {     
                    var context = this;     
                    console.log("this",this)          
                    if (!timer) {                    
                        timer = setTimeout(function() {                        
                            func.apply(context);      
                            // func()                  
                            timer = null;                    
                        }, delay);                
                    }            
                }        
            }    
            //this指向的问题
            /*
                我们需要知道匿名函数中的this会指向调用者所在的对象
                而箭头函数中的this则永久指向一开始定义时所在的对象
                在函数中因为要通过定时器的回调函数来执行toggle()函数
                所以需要用apply()方法将func绑定到了this指向的对象上(也就是当前的li元素)
                不然调用回调函数后this将会指向定时器setTimeout所在的window对象上
                绑定的this指向会覆盖箭头函数中的this指向
            */
            // $('.main>ul>li').hover(throttle(toggle,50));
            
            /*事件冒泡和事件代理问题
                事件冒泡是指子元素触发事件后会向父级元素传递从而导致父级元素也会触发该事件
                事件代理是指通过事件冒泡机制来达到只需要设置父元素事件函数就可以做到被代理者能够触发该事件
                
                在这个案例中如果我们不对父元素对子元素进行事件代理的话
                会导致每个一级菜单触发的事件都是独立与另一个一级菜单的
                而这样即使我们进行节流也没有意义因为事件源不唯一
                所以我们需要通过对父元素(ul)来代理一级菜单的事件达到事件源的统一
                
            */
            /*
                hover事件代理问题
                因为hover是非标准事件所以不能进行事件代理
                所以我们要通过对 mouseenter 或 mouseleave 的代理来实现效果
            */
            //这里需要将一级二级的li标签都要代理，只代理一级菜单无法触发节流效果(待解决疑问)
            $('ul').delegate('li','mouseenter',throttle(toggle,50));
            /*
                优化版：鼠标滑出时关闭所有一级菜单。

                一开始以为只需要通过ul对下级菜单的一个代理就能解决问题 可惜我年轻了呀，
                这里之所以用到了两个ul代理是因为需要触发两次mouseleave，那为什么需要触发两次呢？
                因为当鼠标离开整个菜单时可能是从一级菜单离开也可能是从二级菜单离开
                导致mouseleave事件触发时this指向是不同的，分别指向一级菜单与二级菜单。
                那么我们就需要两次触发（而且是对不同子元素的代理分别为.sub与.first）分别处理
                
            */
            $('ul').delegate('.sub','mouseleave',throttle(close,50));
            $('ul').delegate('.first','mouseleave',throttle(close,50));
            // $('ul').delegate('.secound','mouseleave',throttle(close,50));

        })
    </script>
    <div class="main">
        <ul>
            <li class="first">一级菜单<span></span>
                <ul class="sub">
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                </ul> 
            </li>
            
            <li class="first">一级菜单<span></span><ul class="sub">
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                </ul> </li>
            <li class="first">一级菜单<span></span><ul class="sub">
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                </ul> </li>
            <li class="first">一级菜单<span></span><ul class="sub">
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                </ul> </li>
            <li class="first">一级菜单<span></span><ul class="sub">
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                </ul> </li>
            <li class="first">一级菜单<span></span><ul class="sub">
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                </ul> </li>
            <li class="first">一级菜单<span></span><ul class="sub">
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                    <li class="secound">二级菜单</li>
                </ul> </li>
            <li class="first">一级菜单<span></span><ul class="sub">
                    <li>二级菜单</li>
                    <li>二级菜单</li>
                    <li>二级菜单</li>
                    <li>二级菜单</li>
                </ul> </li>
        </ul>
    </div>
</body>
</html>